// 使用times和sysconf函数来测量一个可执行文件(进程)的进程时间
// 应用代码首先使用argv来传递执行的进程名称，在开始执行的时候记录一个始终滴答数start
// 然后在执行完退出之后再次记录一个时钟滴答数end
// 通过这两个值来计算得到相应的执行时间
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <sys/times.h>

// 时间统计函数
void get_times(clock_t real, struct tms *tmsstart, struct tms *tmsend){
	
	static long clktck = 0;

	// 判断是否第一次获得时间
	if (clktck == 0){
		
		// 第一次获得时间
		clktck = sysconf(_SC_CLK_TCK);
	
		if(clktck < 0){
			perror("调用sysconf函数失败!\n");
		}
	}
	// 进行时间输出
	printf("时钟时间： %7.2f\n", real/(double)clktck);
	printf("用户CPU时间： %7.2f\n", (tmsend->tms_utime - tmsstart->tms_utime)/ (double)clktck);
	printf("系统CPU时间： %7.2f\n", (tmsend->tms_stime - tmsstart->tms_stime)/ (double)clktck);
	printf("子进程时钟时间： %7.2f\n", (tmsend->tms_cutime - tmsstart->tms_cutime)/ (double)clktck);
	printf("子进程系统CPU时间：%7.2f\n", (tmsend->tms_cstime - tmsstart->tms_cstime)/(double)clktck);
	
}

// 执行并对cmd命令计时
void execute_cmd(char *cmd){
	
	// 创建两个时间结构体
	struct tms tmsstart, tmsend;

	// 创建两个clock_t结构体，分别用来存放起止和停止时刻的始终滴答数
	clock_t start, end;

	// status用来记录执行的状态
	int status;

	printf("\n当前执行的命令是：%s\n", cmd);

	// 获得start时间
	if( (start = times(&tmsstart)) == -1){
		perror("调用times函数出错!\n");
	}

	// 执行命令
	if( (status = system(cmd)) < 0){
		perror("调用system函数出错!\n");
	}

	// 获得end时间
	if( (end = times(&tmsend)) == -1){
		perror("调用times函数出错!\n");
	}

	// 计算运行时间
	get_times(end-start, &tmsstart, &tmsend);
}

/*main函数*/
int main(int argc ,char *argv[]){

	int i;

	// 清空标准输出（屏幕）
	setbuf(stdout, NULL);

	if(argc != 2){
		printf("请输入正确的命令!\n");
		return -2;
	}	

	// 调用execute_cmd函数执行命令
	execute_cmd(argv[1]);

	exit(0);
}
